package com.tryee.wx.config.servlet;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ImageUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.tryee.common.utils.DateUtils;
import com.tryee.wx.config.constant.WeiXin;
import com.tryee.wx.config.utils.SHA1Util;
import com.tryee.wx.config.utils.WxUtils;
import com.tryee.wx.domain.User;
import com.tryee.wx.domain.UserMsg;
import com.tryee.wx.service.IUserMsgService;
import com.tryee.wx.service.IUserService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/wx")
@Configuration
public class ServletController {

    private Logger logger = LoggerFactory.getLogger(ServletController.class);

    @Value("${wx.token}")
    private String token;

    @Value("${wx.chatId}")
    private String chatId;

    @Value("${wx.subscribeContent}")
    private String subscribeContent;

    @Autowired
    private IUserService userService;

    @Autowired
    private IUserMsgService userMsgService;
    @Autowired
    private WxUtils wxUtils;


    @GetMapping("/servlet")
    public String servlet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String signatures = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");
        String myString = SHA1Util.getSHA1(token, timestamp, nonce, signatures);
        if (signatures.equals(myString)) {
            logger.info("微信签名校验成功！");
            return echostr;
        } else {
            logger.info("微信签名校验失败！");
            return "";
        }
    }

    @PostMapping("/servlet")
    public String event(HttpServletRequest request, HttpServletResponse response) throws IOException {
        InputStream inputStream = request.getInputStream();

        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String line = "";
        StringBuilder sb = new StringBuilder();
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
            sb.append(line);
        }
        Map<String, Object> map = XmlUtil.xmlToMap(sb.toString());


        return doEvent(map);
    }

    /**
     * 处理事件
     *
     * @param map
     */
    private String doEvent(Map<String, Object> map) {
        if (!CollectionUtils.isEmpty(map.values())) {
            String eventKey = (String) map.get("Event");
            if (eventKey != null) {
                switch (eventKey) {
                    //关注事件
                    case "subscribe":
                        logger.info("用户关注了公众号！");
                        return doOrUnDoSubscribe(map);
                    case "unsubscribe":
                        logger.info("用户取消关注了！");
                        return doOrUnDoSubscribe(map);
                    case "LOCATION":
                        logger.info("用户上报地理位置了");
                        break;
                    case "VIEW":
                    case "CLICK":
                        logger.info("用户点击自定义菜单了");
                        logger.info("EventKey:{}", map.get("EventKey"));
                        break;
                    default:
                        break;
                }
            } else if (map.get("MsgType") != null) {
                return doReceiveMsg(map);
            }
        }

        return "";
    }

    /**
     * 处理接收普通消息
     *
     * @param map xml转换的map
     */
    private String doReceiveMsg(Map<String, Object> map) {
        String msgType = (String) map.get("MsgType");
        switch (msgType) {
            //文本消息
            case "text":
                receiveText(map);
                break;
            //图片消息
            case "image":
                receiveImage(map);
                break;
        }

        return "";
    }


    /**
     * 接收图片消息
     * @param map
     */
    private void receiveImage(Map<String, Object> map) {
        String msgType = (String) map.get("MsgType");
        String toUsername = (String) map.get("ToUserName");
        String fromUserName = (String) map.get("FromUserName");
        String createTime = (String) map.get("CreateTime");
        String msgId = (String) map.get("MsgId");
        String picUrl = (String) map.get("PicUrl");
        String mediaId = (String) map.get("MediaId");

        UserMsg userMsg = new UserMsg();
        userMsg.setMsgType(msgType);
        userMsg.setToUserName(toUsername);
        userMsg.setFromUserName(fromUserName);
        userMsg.setCreateTime(DateUtil.date(new Date()));
        userMsg.setMsgId(msgId);
        userMsg.setPicUrl(picUrl);
        userMsg.setMediaId(mediaId);

        userMsgService.insertUserMsg(userMsg);
    }

    /**
     * 接收文本消息
     * @param map
     */
    private void receiveText(Map<String, Object> map) {
        String msgType = (String) map.get("MsgType");
        String toUsername = (String) map.get("ToUserName");
        String fromUserName = (String) map.get("FromUserName");
        String createTime = (String) map.get("CreateTime");
        String msgId = (String) map.get("MsgId");
        String content = (String) map.get("Content");

        UserMsg userMsg = new UserMsg();
        userMsg.setMsgType(msgType);
        userMsg.setToUserName(toUsername);
        userMsg.setFromUserName(fromUserName);
        userMsg.setCreateTime(DateUtil.date(new Date()));
        userMsg.setMsgId(msgId);
        userMsg.setContent(content);

        userMsgService.insertUserMsg(userMsg);
    }


    /**
     * 关注或取消公众号-更新用户信息
     *
     * @param map
     */
    private String doOrUnDoSubscribe(Map<String, Object> map) {
        String openid = (String) map.get("FromUserName");
        Map<String, Object> usermap = new HashMap<>();
        usermap.put("access_token", wxUtils.getToken());
        usermap.put("openid", openid);
        usermap.put("lang", "zh_CN");
        String userInfo = HttpUtil.get(WeiXin.USERINFO, usermap);

        JSONObject jsonObject = JSONUtil.parseObj(userInfo);

        //保存或更新用户数据
        return insertOrUpdateUser(jsonObject);
    }

    /**
     * 用户数据插入数据表
     *
     * @param jsonObject 用户json数据
     */
    private String insertOrUpdateUser(JSONObject jsonObject) {


        User user = new User();
        user.setOpenid(jsonObject.getStr("openid"));

        //首先查看用户是否存在，如果存在则更新
        List<User> users = userService.selectUserList(user);

        user.setSubscribe(jsonObject.getInt("subscribe"));
        user.setNickname(jsonObject.getStr("nickname"));
        user.setSex(jsonObject.getInt("sex"));
        user.setLanguage(jsonObject.getStr("language"));
        user.setCity(jsonObject.getStr("city"));
        user.setProvince(jsonObject.getStr("province"));
        user.setCountry(jsonObject.getStr("country"));
        user.setHeadimgurl(jsonObject.getStr("headimgurl"));
        user.setSubscribeTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        user.setUnionid(jsonObject.getStr("unionid"));
        user.setRemark(jsonObject.getStr("remark"));
        user.setGroupid(jsonObject.getStr("groupid"));
        user.setTagidList(jsonObject.getStr("tagid_list"));
        user.setSubscribeScene(jsonObject.getStr("subscribe_scene"));
        user.setQrScene(jsonObject.getStr("qr_scene"));
        user.setQrSceneStr(jsonObject.getStr("qr_scene_str"));


        if (users.size() != 0) {
            //用户存在则更新
            user.setId(users.get(0).getId());
            userService.updateUser(user);
        } else {
            //用户不存在，插入数据表
            userService.insertUser(user);
            //用户首次关注输出关注内容

        }

        return this.sendText(user.getOpenid(), subscribeContent);
    }


    /**
     * 发送文本消息
     *
     * @param ToUserName 发送给用户的openid
     * @param content    发送给用户的内容
     * @return
     */
    private String sendText(String ToUserName, String content) {

        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        sb.append("<ToUserName><![CDATA[" + ToUserName + "]]></ToUserName>");
        sb.append("<FromUserName><![CDATA[" + chatId + "]]></FromUserName>");
        sb.append("<CreateTime>" + DateUtil.now() + "</CreateTime>");
        sb.append("<MsgType><![CDATA[text]]></MsgType>");
        sb.append("<Content><![CDATA[" + content + "]]></Content>");
        sb.append("</xml>");
        return sb.toString();

    }
}
